import 'dart:collection';
import 'dart:convert';

import 'package:mqtt5_client/mqtt5_client.dart';
import 'package:mqtt5_client/mqtt5_server_client.dart';
import 'package:protobuf/protobuf.dart';
import 'package:simple_logger/simple_logger.dart';
import 'package:typed_data/src/typed_buffer.dart';
import 'package:wk_robot2/app/event/MsgContentEvent.dart';
import 'package:wk_robot2/app/robot_comm/msg_callback.dart';
import 'package:wk_robot2/app/robot_comm/robot_status_listner.dart';

import 'package:fixnum/fixnum.dart' as $fixnum;
import 'package:wk_robot2/generated/AlphaRequest.pb.dart';

import '../../generated/AlphaResponse.pb.dart';
import '../models/Devices.dart';
import '../utils/CommonUtil.dart';
import 'event_handler.dart';

class MqttCommManager {
  String Tag = "MqttCommManager";
  //String host = "zxlab-dev.ubtrobot.com"; // 开发环境
  //String host = "zxcnagent.ubtrobot.com"; //测试环境
  String host = "121.41.1.236"; //测试环境

  int port = 1883;
  String _productName = "wukong2";
  late MqttServerClient client;
  HashMap<$fixnum.Int64, Function(AlphaResponse msg)> msgCallbacks = HashMap();
  HashMap<int, EventHandler> _eventHandlers = HashMap();

  Function(String, bool) _onlineListner = (String id, bool isOnline){};

  $fixnum.Int64 _sendSerialId = $fixnum.Int64(1);

  String _statusTopicSuffix = "onlinestatus";
  String _responseTopicSuffix = "command_response";
  String _eventTopicSuffix = "event";
  String _responseTopic = "";
  String _eventTopic = "";

  // 私有构造函数，防止外部实例化
  MqttCommManager._internal() {
    client = MqttServerClient(host, '');
  }
  // 静态变量存储唯一的实例
  static final MqttCommManager _instance = MqttCommManager._internal();
  // 工厂构造函数返回现有的实例
  factory MqttCommManager() {
    return _instance;
  }

  Future<bool> connectToServer() async {
    if(client.connectionStatus?.state == MqttConnectionState.connected || client.connectionStatus?.state == MqttConnectionState.connecting){
      return true;
    }

    client.port = port;
    // 设置客户端标识符（client ID）
    client.clientIdentifier = "${CommonUtil.getLoginUserId().toString()}_${CommonUtil.getDeviceId()}";
    // 设置连接超时时间

    client.connectionMessage = MqttConnectMessage()
        .withClientIdentifier(client.clientIdentifier)
        .startClean(); // 清理会话
    client.keepAlivePeriod = 30;
    client.keepAlivePeriod = 30 * 60;
    client.autoReconnect = true;
    client.onAutoReconnect = () {
      print('$Tag Auto reconnecting...');
    };

    // 设置连接回调函数
    client.onConnected = _onConnected;
    client.onDisconnected = _onDisconnected;
    client.onSubscribed = _onSubscribed;
    client.pongCallback = _pong;

    try {
      print('$Tag 开始连接到MQTT服务器..., userid: ${client.clientIdentifier}');
      await client.connect();
      client.updates.listen((List<MqttReceivedMessage<MqttMessage?>>? c) {
        final recMess = c![0].payload as MqttPublishMessage;
        final payload = recMess.payload.message!;
        if (c![0].topic!.contains(_statusTopicSuffix)) {
          String res = utf8.decode(payload.toList());

          final Map<String, dynamic> jsonMap = jsonDecode(res);

          // 解析 clientid
          final String? clientId = jsonMap['clientid'];

          // 解析在线状态
          bool isOnline = false;
          final String? event = jsonMap['event'];
          if (event == 'client.connected') {
            isOnline = true;
          } else if (event == 'client.disconnected') {
            isOnline = false;
          } else {
            print('$Tag Unknown event type: $event');
            return;
          }

          print('$Tag robotid: $clientId, isOnline: $isOnline: ');
          // 在这里你可以根据解析出来的 clientid 和 isOnline 做进一步处理
          if(clientId != null) {
            _onlineListner.call(clientId, isOnline);
          }

        } else if (c![0].topic == _responseTopic) {
          // if(recMess.header)
          AlphaResponse alphaMessage = AlphaResponse.fromBuffer(payload);
          print('$Tag receive response: ${alphaMessage.header}');

          msgCallbacks[alphaMessage.header.sendSerial]?.call(alphaMessage);

          if(alphaMessage.header.isLastReponse){
            msgCallbacks.remove(alphaMessage.header.sendSerial);
          }
        }else if (c![0].topic == _eventTopic) {
          // if(recMess.header)
          AlphaResponse alphaMessage = AlphaResponse.fromBuffer(payload);
          print('$Tag reveice event: ${alphaMessage.header}');

          _eventHandlers[alphaMessage.header.commandId]?.handleEvent(alphaMessage);

        }
      });
      return true;
    } catch (e) {
      print('$Tag 连接失败: $e');
      client.disconnect();
      return false;
    }
  }

  void disconnectToServer(){
    client.disconnect();
  }

  Future<bool> isConnected() async {
    if(client.connectionStatus?.state == MqttConnectionState.connected){
      return true;
    }
    return false;
  }

  Future<void> subscribeMsg(List<Device> boundDevices, Function(String, bool) onlineListner) async {
    if(!(await isConnected())){
       print("$Tag ubt_error, mqtt is not connected, subscribeMsg failed");
       return;
    }
    _onlineListner = onlineListner;

    boundDevices.forEach((device){
      String topicOnlineStatus = "/${device.robotUserId}/${_statusTopicSuffix}";
      client.subscribe(topicOnlineStatus, MqttQos.atLeastOnce);
      if(device.selected){
        if(device.robotUserId != null) {
          _responseTopic = "${_productName}/${device.robotUserId}/${_responseTopicSuffix}";
          _eventTopic = "${_productName}/${device.robotUserId}/${_eventTopicSuffix}";

          client.subscribe(_responseTopic, MqttQos.exactlyOnce);
          client.subscribe(_eventTopic, MqttQos.exactlyOnce);
        }
      }
    });
  }

  void unsubscribeMsg(String deviceId) {
    String topicOnlineStatus = "/${deviceId}/${_statusTopicSuffix}";
    client.unsubscribeStringTopic(topicOnlineStatus);
    String responseTopic = "${_productName}/${deviceId}/${_responseTopicSuffix}";
    client.unsubscribeStringTopic(responseTopic);
    String eventTopic = "${_productName}/${deviceId}/${_eventTopicSuffix}";
    client.unsubscribeStringTopic(eventTopic);
  }

  void sendCmd(int cmdId, GeneratedMessage requestMsg,
      void Function(AlphaResponse msg) msgCallback) {
    String? robotId = CommonUtil.getCurrentSelectedRobot().robotUserId;
    if(robotId == null){
      print('$Tag ubt_error, 当前没有绑定设备');
      return;
    }

    _sendSerialId ++;
    msgCallbacks[_sendSerialId] = msgCallback;

    AlphaRequestHeader alphaMessageHeader = new AlphaRequestHeader(
      commandId: cmdId,
      sendSerial: _sendSerialId,
    );
    AlphaRequest alphaRequest = new AlphaRequest(
        header: alphaMessageHeader, bodyData: requestMsg.writeToBuffer());

    String topic = "${_productName}/${robotId}/command";
    Uint8Buffer uint8Buffer = Uint8Buffer();
    uint8Buffer.addAll(alphaRequest.writeToBuffer());

    try {
      client.publishMessage(topic, MqttQos.exactlyOnce, uint8Buffer);
      print('$Tag 已发送消息到主题: $topic, 消息内容: ${alphaRequest.writeToJson()}');
    }catch (e){
      print('$Tag 已发送消息到主题: $topic, 出错， ${e.toString()}');
    }
  }

  void subScribeEvent(int eventId, EventHandler eventHandler){
    _eventHandlers[eventId] = eventHandler;
  }

  void subScribeEvent2(int eventId, EventHandler eventHandler){
    _eventHandlers[eventId] = eventHandler;
  }



  void unSubScribeEvent(int eventId){
    _eventHandlers.remove(eventId);
  }

  void _onConnected() {
    print('$Tag 成功连接到mqtt');
    // 在这里可以安全地执行订阅或其他操作
  }

  void _onDisconnected() {
    print('$Tag 和mqtt断开连接');
  }

  void _onSubscribed(MqttSubscription topic) {
    print('$Tag 订阅主题: $topic');
  }

  void _pong() {
    //print('Ping response client callback invoked');
  }

}
